import { Context } from 'koa';
import { AppContext } from '@/types';
import * as response from '@/utils/response';
import { User, LoginLog, File, Tenant } from '@/models';
import { Op } from 'sequelize';
import os from 'os';
import sequelize from '@/db';

/**
 * 仪表盘控制器
 */
export class DashboardController {
  /**
   * 获取仪表盘统计数据
   */
  async getStats(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;

    try {
      const stats: any = {};

      // 系统统计（仅超级管理员可见）
      if (user?.type === 'super_admin') {
        // 租户统计
        const totalTenants = await Tenant.count();
        const activeTenants = await Tenant.count({
          where: { status: 'active' },
        });

        stats.tenants = {
          total: totalTenants,
          active: activeTenants,
          inactive: totalTenants - activeTenants,
        };
      }

      // 用户统计
      const whereClause: any = {};
      if (user?.type !== 'super_admin' && user?.tenantId) {
        whereClause.tenantId = user.tenantId;
      }

      const totalUsers = await User.count({ where: whereClause });
      const activeUsers = await User.count({
        where: { ...whereClause, status: 'active' },
      });

      stats.users = {
        total: totalUsers,
        active: activeUsers,
        inactive: totalUsers - activeUsers,
      };

      // 登录统计（最近7天）
      const sevenDaysAgo = new Date();
      sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

      const loginWhereClause: any = {
        loginTime: { [Op.gte]: sevenDaysAgo },
      };
      if (user?.type !== 'super_admin' && user?.tenantId) {
        loginWhereClause.tenantId = user.tenantId;
      }

      const totalLogins = await LoginLog.count({
        where: loginWhereClause,
      });

      const successLogins = await LoginLog.count({
        where: { ...loginWhereClause, status: 'success' },
      });

      const failedLogins = await LoginLog.count({
        where: { ...loginWhereClause, status: 'failed' },
      });

      // 获取独立登录用户数
      const uniqueUsers = await LoginLog.count({
        where: { ...loginWhereClause, status: 'success' },
        distinct: true,
        col: 'userId',
      });

      stats.logins = {
        total: totalLogins,
        success: successLogins,
        failed: failedLogins,
        uniqueUsers,
        successRate: totalLogins > 0 ? ((successLogins / totalLogins) * 100).toFixed(2) : '0',
      };

      // 文件统计
      const fileWhereClause: any = {};
      if (user?.type !== 'super_admin' && user?.tenantId) {
        fileWhereClause.tenantId = user.tenantId;
      }

      const totalFiles = await File.count({ where: fileWhereClause });
      const totalSize = await File.sum('size', { where: fileWhereClause }) || 0;

      stats.files = {
        total: totalFiles,
        totalSize,
        totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
      };

      // 服务器信息
      stats.server = {
        platform: os.platform(),
        arch: os.arch(),
        hostname: os.hostname(),
        cpus: os.cpus().length,
        totalMemory: (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB',
        freeMemory: (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB',
        uptime: Math.floor(os.uptime() / 3600) + ' 小时',
        nodeVersion: process.version,
      };

      response.success(ctx, stats);
    } catch (error) {
      console.error('获取仪表盘统计数据失败:', error);
      ctx.throw(500, '获取统计数据失败');
    }
  }

  /**
   * 获取登录趋势数据（最近7天）
   */
  async getLoginTrend(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { user } = appCtx.state;

    try {
      const sevenDaysAgo = new Date();
      sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
      sevenDaysAgo.setHours(0, 0, 0, 0);

      const whereClause: any = {
        loginTime: { [Op.gte]: sevenDaysAgo },
      };
      if (user?.type !== 'super_admin' && user?.tenantId) {
        whereClause.tenantId = user.tenantId;
      }

      // 按天统计登录数据
      const trends = await LoginLog.findAll({
        attributes: [
          [sequelize.fn('DATE', sequelize.col('login_time')), 'date'],
          [sequelize.fn('COUNT', '*'), 'total'],
          [
            sequelize.fn(
              'SUM',
              sequelize.literal("CASE WHEN status = 'success' THEN 1 ELSE 0 END")
            ),
            'success',
          ],
          [
            sequelize.fn(
              'SUM',
              sequelize.literal("CASE WHEN status = 'failed' THEN 1 ELSE 0 END")
            ),
            'failed',
          ],
        ],
        where: whereClause,
        group: [sequelize.fn('DATE', sequelize.col('login_time'))],
        order: [[sequelize.fn('DATE', sequelize.col('login_time')), 'ASC']],
        raw: true,
      });

      response.success(ctx, trends);
    } catch (error) {
      console.error('获取登录趋势数据失败:', error);
      ctx.throw(500, '获取登录趋势数据失败');
    }
  }

  /**
   * 获取实时服务器状态
   */
  async getServerStatus(ctx: Context) {
    try {
      const cpuUsage = process.cpuUsage();
      const memUsage = process.memoryUsage();

      const status = {
        cpu: {
          user: cpuUsage.user,
          system: cpuUsage.system,
        },
        memory: {
          rss: (memUsage.rss / 1024 / 1024).toFixed(2) + ' MB',
          heapTotal: (memUsage.heapTotal / 1024 / 1024).toFixed(2) + ' MB',
          heapUsed: (memUsage.heapUsed / 1024 / 1024).toFixed(2) + ' MB',
          external: (memUsage.external / 1024 / 1024).toFixed(2) + ' MB',
        },
        system: {
          totalMemory: (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB',
          freeMemory: (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB',
          usedMemory: ((os.totalmem() - os.freemem()) / 1024 / 1024 / 1024).toFixed(2) + ' GB',
          memoryUsagePercent: (((os.totalmem() - os.freemem()) / os.totalmem()) * 100).toFixed(2) + '%',
          uptime: Math.floor(os.uptime() / 3600) + ' 小时',
          loadavg: os.loadavg(),
        },
        timestamp: Date.now(),
      };

      response.success(ctx, status);
    } catch (error) {
      console.error('获取服务器状态失败:', error);
      ctx.throw(500, '获取服务器状态失败');
    }
  }
}

export default new DashboardController();

